home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.08 Aug 91 / Modeless SF Source / CSFDialogs.p < prev    next >
Encoding:
Text File  |  1991-04-10  |  46.6 KB  |  2,378 lines  |  [TEXT/PJMM]

  1. { Written by Brendan Murphy }
  2. { Version 1.0 }
  3.  
  4. UNIT CSFDialogs;
  5.  
  6. INTERFACE { TwilightZone }
  7.  
  8. USES
  9.     TCL, Disks;
  10. { Make sure you have included 'Disks.p' in your project }
  11.  
  12. CONST
  13.     cmdDiskEvent = 552;
  14.     ScrDmpEnb = $2F8;  { Global }
  15.  
  16.     { Button stuff }
  17.     kScrollBarWidth = 15;
  18.     kButtonHeight = 17;
  19.     kGetButtonOffset = 264;
  20.     kSaveButtonOffset = 226;
  21.  
  22.     { Resource IDs }
  23.     kRadioButton = 1;
  24.     kCheckButton = 2;
  25.     KPushButton = 3;
  26.  
  27.     { Buttons }
  28.     kCancelButton = 20001;
  29.     kEjectButton = 20002;
  30.     kDriveButton = 20003;
  31.     kOpenButton = 20004;
  32.     kSaveButton = 20005;
  33.  
  34.     { More commands }
  35.     kSelection = 21000;
  36.     kEmptyText = 21001;
  37.     kNonEmptyText = 21002;
  38.  
  39.     { Red Alert Errors }
  40.     kDiskNotFound = -3994;
  41.     kSystemError = -3995;
  42.     kExistingFile = -3996;
  43.     kLockedDisk = -3997;
  44.  
  45. TYPE
  46.  
  47. { Shows volume name and icon }
  48.     CSFVolumeBox = OBJECT(CPane)
  49.             PROCEDURE Draw (VAR Area: Rect);
  50.             Override;
  51.             PROCEDURE DoClick (hitPt: Point; modifierKeys: integer; when: longint);
  52.             Override;
  53.         END;
  54.  
  55.  
  56. { Text edit box for save dialog }
  57.     CSFEditText = OBJECT(CEditText)
  58.             fEmpty: Boolean; { Anybody Home? }
  59.  
  60.             PROCEDURE IEditText (anEnclosure: CView; aSupervisor: CBureaucrat; aWidth, aHeight, aHEncl, aVEncl: integer; aHSizing, aVSizing: SizingOption; aLineWidth: integer);
  61.             Override;
  62.             PROCEDURE DoKeyDown (theChar: char; keyCode: Byte; macEvent: EventRecord);
  63.             Override;
  64.             PROCEDURE SetText;
  65.             FUNCTION IsEmpty: Boolean;
  66.             PROCEDURE Dawdle (VAR maxSleep: Longint);
  67.             Override;
  68.             PROCEDURE SelectText;
  69.             FUNCTION GetStr255: Str255;
  70.         END;
  71.  
  72.  
  73. { Main window class }
  74.     CSFWindow = OBJECT(CWindow)
  75.             fInitTime: Boolean;
  76.  
  77.             { Button references }
  78.             fEject, fDrive, fCancel: CButton;
  79.  
  80.             fVolumeBox: CSFVolumeBox;
  81.  
  82.             { Holds the file listings }
  83.             fFileList: ListHandle;
  84.             fViewRect: Rect;
  85.  
  86.             { Holds the path to the directory }
  87.             fPathList: ListHandle;
  88.             fPathRect: Rect;
  89.             fMenuWidth: Integer;
  90.             fMenuHeight: Integer;
  91.  
  92.             fDriveIndex: Integer;
  93.             fDrive1, fDrive2: Integer;
  94.  
  95.             { Internal directory information }
  96.             fCurrentWD: Integer; { Holds current working directory }
  97.             fGood: Boolean;
  98.             fName: Str255;
  99.             fVName: Str255;
  100.  
  101.             PROCEDURE ICSFWindow (TheDirector: CDirector);
  102.             PROCEDURE MoreInitializations;
  103.             PROCEDURE SetfViewRect;
  104.             PROCEDURE DoKeyDown (theChar: char; keyCode: Byte; macEvent: EventRecord);
  105.             Override;
  106.             PROCEDURE DoCommand (TheCommand: Longint);
  107.             Override;
  108.             PROCEDURE Update;
  109.             Override;
  110.             PROCEDURE MoreUpdates;
  111.             PROCEDURE Free;
  112.             Override;
  113.             PROCEDURE DoClick (hitPt: Point; modifierKeys: integer; when: longint);
  114.             Override;
  115.             PROCEDURE Activate;
  116.             Override;
  117.             PROCEDURE Deactivate;
  118.             Override;
  119.             PROCEDURE Close;
  120.             Override;
  121.  
  122.             FUNCTION CountDrives: Integer;
  123.             FUNCTION GetNextVol: Integer;
  124.             FUNCTION CheckDrives: Boolean;
  125.  
  126.             PROCEDURE DoEject;
  127.             PROCEDURE DoDrive;
  128.             PROCEDURE DoCancel;
  129.             PROCEDURE DoStatus;
  130.  
  131.             FUNCTION FileFilter (ParamBlock: CInfoPBPtr): Boolean;
  132.             FUNCTION ActiveFilter (ParamBlock: CInfoPBPtr): Boolean;
  133.             PROCEDURE FillDialog (VRefNum: Integer);
  134.  
  135.             PROCEDURE SetPathRect;
  136.             PROCEDURE FindPath (VRefNum: Integer);
  137.             FUNCTION FindSelection: Str255;
  138.  
  139.             PROCEDURE DoSelection;
  140.             PROCEDURE FileSelected (TheReply: SFReply);
  141.  
  142.             FUNCTION RedAlert (AlertID: Integer): Integer;
  143.         END;
  144.  
  145.  
  146. { Subclasses of main window }
  147. { You will want to override these subclasses }
  148.  
  149.     CSFGetWindow = OBJECT(CSFWindow)
  150.             fOpen: CButton;
  151.  
  152.             PROCEDURE MoreInitializations;
  153.             Override;
  154.             PROCEDURE DoKeyDown (theChar: char; keyCode: Byte; macEvent: EventRecord);
  155.             Override;
  156.             PROCEDURE SetfViewRect;
  157.             Override;
  158.             PROCEDURE MoreUpdates;
  159.             Override;
  160.             PROCEDURE DoStatus;
  161.             Override;
  162.             PROCEDURE DoClick (hitPt: Point; modifierKeys: integer; when: longint);
  163.             Override;
  164.             PROCEDURE DoCommand (TheCommand: Longint);
  165.             Override;
  166.             PROCEDURE Free;
  167.             Override;
  168.             PROCEDURE DoOpen;
  169.         END;
  170.  
  171.  
  172.     CSFSaveWindow = OBJECT(CSFWindow)
  173.             fSave: CButton;
  174.             fFileName: CSFEditText;
  175.             fPromptString: Str255;
  176.  
  177.             PROCEDURE MoreInitializations;
  178.             Override;
  179.             PROCEDURE SetfViewRect;
  180.             Override;
  181.             FUNCTION ActiveFilter (ParamBlock: CInfoPBPtr): Boolean;
  182.             Override;
  183.             PROCEDURE Activate;
  184.             Override;
  185.             PROCEDURE DoCommand (TheCommand: Longint);
  186.             Override;
  187.             PROCEDURE MoreUpdates;
  188.             Override;
  189.             PROCEDURE Free;
  190.             Override;
  191.             FUNCTION FileExists (vRefNum: Integer; TheName: Str255): Boolean;
  192.             PROCEDURE DoSave;
  193.         END;
  194.  
  195.  
  196. { Also make sure to create subclasses of these directors }
  197.  
  198.     CSFDialog = OBJECT(CDirector)
  199.             PROCEDURE ICSFDialog;
  200.         END;
  201.  
  202.  
  203.     CSFGetDialog = OBJECT(CSFDialog)
  204.             PROCEDURE ICSFDialog;
  205.             Override;
  206.         END;
  207.  
  208.  
  209.     CSFSaveDialog = OBJECT(CSFDialog)
  210.             PROCEDURE ICSFDialog;
  211.             Override;
  212.         END;
  213.  
  214.  
  215. { You don't have to do anything with the switchboard since }
  216. { it is installed by the CSFApplication }
  217.  
  218.     CSFSwitchboard = OBJECT(CSwitchBoard)
  219.             PROCEDURE DoDiskEvent (macEvent: EventRecord);
  220.             Override;
  221.         END;
  222.  
  223.  
  224. { Make sure this class is installed in your application! }
  225.  
  226.     CSFApplication = OBJECT(CApplication)
  227.             PROCEDURE ICSFApplication (extraMasters: integer; aRainyDayFund, aCreditLimit: Size);
  228.         END;
  229.  
  230.  
  231. IMPLEMENTATION
  232.  
  233. VAR
  234. { This list handle is critcal to the ClickLoop routine. }
  235. { It holds the current path menu list. }
  236.     ThePathList: ListHandle;
  237.     ThePathCell: Cell;
  238.  
  239.  
  240. FUNCTION IsDirectory (ParamBlock: CInfoPBPtr): Boolean;
  241. { Is this a directory? }
  242.  
  243.     BEGIN
  244.  
  245.         IsDirectory := BitTst(@ParamBlock^.ioFLAttrib, 3);
  246.  
  247.     END;
  248.  
  249.  
  250. PROCEDURE DropShadow (TheRect: Rect);
  251. { Draw a shadow around the box }
  252.  
  253.     BEGIN
  254.  
  255.         Moveto(TheRect.Left + 1, TheRect.Bottom);
  256.         Lineto(TheRect.Right, TheRect.Bottom);
  257.         Lineto(TheRect.Right, TheRect.Top + 1);
  258.  
  259.     END;
  260.  
  261.  
  262. PROCEDURE FKeyEnable (OnOff: Boolean);
  263. { Turn off function keys }
  264. { Can't normaly intercept all disk events }
  265. { because they are masked out by the system }
  266. { before they are put in the event queue. }
  267.  
  268.     VAR
  269.         P: Ptr;
  270.  
  271.     BEGIN
  272.  
  273.         { Enable Shift-Command-Keys }
  274.         P := Ptr(ScrDmpEnb);
  275.         IF OnOff THEN
  276.             P^ := $FF
  277.         ELSE
  278.             P^ := $00
  279.  
  280.     END;
  281.  
  282.  
  283. FUNCTION GetCellContents (TheCell: Cell; TheList: Listhandle): Str255;
  284. { Transform the cell data into a Pascal string. }
  285.  
  286.     VAR
  287.         TempStr: Str255;
  288.         DataLength: Integer;
  289.  
  290.     BEGIN
  291.  
  292.         TempStr := '';
  293.         DataLength := 255;
  294.         LGetCell(Ptr(Longint(@TempStr) + 1), DataLength, TheCell, TheList);
  295.         BlockMove(Ptr(Longint(@DataLength) + 1), @TempStr, 1);
  296.         GetCellContents := TempStr;
  297.  
  298.     END;
  299.  
  300.  
  301. FUNCTION ClickLoop: Boolean;
  302. { Gives those pull down menus that special flavor }
  303. { Since we use a custom LDEF, we must roll our own here }
  304. { and damn the torpedos!!! }
  305.  
  306.     VAR
  307.         ThePoint, TheCell, TheNewCell: Point;
  308.         Contents: Str255;
  309.         OffSet: Integer;
  310.  
  311.     BEGIN
  312.  
  313.         OffSet := 0;
  314.         WHILE StillDown DO
  315.             BEGIN
  316.                 GetMouse(ThePoint);
  317.                 IF NOT PtInRect(ThePoint, ThePathList^^.rView) THEN
  318.                     BEGIN
  319.                         { We are not in the menu }
  320.                         SetPt(TheCell, 0, 0);
  321.  
  322.                         { Cell Selected? }
  323.                         IF LGetSelect(True, TheCell, ThePathList) THEN
  324.                             BEGIN
  325.                                 LSetSelect(False, TheCell, ThePathList);
  326.                                 SetPt(ThePathCell, 0, 0);
  327.                             END;
  328.  
  329.                         { Should we scroll? }
  330.                         IF (ThePoint.h > ThePathList^^.rView.Left) AND (ThePoint.h < ThePathList^^.rView.Right) THEN
  331.                             BEGIN
  332.                                 { Up or down? }
  333.                                 IF (ThePoint.v >= ThePathList^^.rView.Top) THEN
  334.                                     BEGIN
  335.                                         SetPt(TheCell, 0, ((ThePathList^^.rView.Bottom - ThePathList^^.rView.Top + 1) DIV ThePathList^^.CellSize.v) + Offset);
  336.                                         IF TheCell.v < ThePathList^^.dataBounds.Bottom THEN
  337.                                             BEGIN
  338.                                                 LScroll(0, 1, ThePathList);
  339.                                                 IF Offset < ThePathList^^.dataBounds.Bottom THEN
  340.                                                     Offset := Offset + 1;
  341.                                             END;
  342.                                     END
  343.                                 ELSE
  344.                                     BEGIN
  345.                                         SetPt(TheCell, 0, ((ThePathList^^.rView.Top - 1) DIV ThePathList^^.CellSize.v) + Offset);
  346.                                         IF TheCell.v > 0 THEN
  347.                                             BEGIN
  348.                                                 LScroll(0, -1, ThePathList);
  349.                                                 IF Offset > 0 THEN
  350.                                                     Offset := Offset - 1;
  351.                                             END;
  352.                                     END;
  353.                             END;
  354.                     END
  355.                 ELSE
  356.                     BEGIN
  357.                         { We are in the menu }
  358.                         SetPt(TheCell, 0, 0);
  359.                         IF LGetSelect(True, TheCell, ThePathList) THEN
  360.                             BEGIN
  361.                                 SetPt(TheNewCell, 0, ((ThePoint.v - ThePathList^^.rView.Top) DIV ThePathList^^.CellSize.v) + Offset);
  362.                                 { Do we need to select a cell? }
  363.                                 IF TheNewCell.v <> TheCell.v THEN
  364.                                     BEGIN
  365.                                         LSetSelect(False, TheCell, ThePathList);
  366.                                         LSetSelect(True, TheNewCell, ThePathList);
  367.                                         ThePathCell := TheNewCell;
  368.                                     END;
  369.                             END
  370.                         ELSE
  371.                             BEGIN
  372.                                 { Nothing turned on so turn something on }
  373.                                 SetPt(TheCell, 0, ((ThePoint.v - ThePathList^^.rView.Top) DIV ThePathList^^.CellSize.v) + Offset);
  374.                                 LSetSelect(True, TheCell, ThePathList);
  375.                                 ThePathCell := TheCell;
  376.                             END;
  377.                     END;
  378.             END;
  379.  
  380.         { Scroll menu back }
  381.         IF Offset > 0 THEN
  382.             BEGIN
  383.                 LDoDraw(False, ThePathList);
  384.                 LScroll(0, -Offset, ThePathList);
  385.                 LDoDraw(True, ThePathList);
  386.             END;
  387.  
  388.         ClickLoop := False;
  389.  
  390.     END;
  391.  
  392.  
  393. FUNCTION ChangeDirectory (VRefNum: Integer; TheFolder: Str255): Integer;
  394. { Change the working directory }
  395.  
  396.     VAR
  397.         ParamBlock: CInfoPBPtr;
  398.         WDBlock: WDPBPtr;
  399.         Err: OSErr;
  400.  
  401.     BEGIN
  402.  
  403.         ParamBlock := CInfoPBPtr(NewPtr(SizeOf(CInfoPBRec)));
  404.         WDBlock := WDPBPtr(NewPtr(SizeOf(WDPBRec)));
  405.  
  406.         { Find out where we are }
  407.         Err := NoErr;
  408.         WITH WDBlock^ DO
  409.             BEGIN
  410.                 ioCompletion := NIL;
  411.                 ioNamePtr := NIL;
  412.                 ioVRefNum := VRefNum;
  413.                 ioWDIndex := 0;
  414.                 ioWDProcID := 0;
  415.             END;
  416.         Err := PBGetWDInfo(WDBlock, False);
  417.  
  418.         { Open directory named TheFolder. }
  419.         { You would think Apple would provide }
  420.         { more higher level routines to do this }
  421.         { kind of work. }
  422.         ParamBlock^.ioDrParID := WDBlock^.ioWDDirID;
  423.         WITH ParamBlock^ DO
  424.             BEGIN
  425.                 ioCompletion := NIL;
  426.                 ioNamePtr := @TheFolder;
  427.                 ioVRefNum := VRefNum;
  428.                 ioDrDirID := 0;
  429.                 ioDirID := 0;
  430.                 ioFVersNum := 0;
  431.                 ioFDirIndex := 0;
  432.             END;
  433.         Err := PBGetCatInfo(ParamBlock, False);
  434.  
  435.         { Open working directory }
  436.         WITH WDBlock^ DO
  437.             BEGIN
  438.                 ioCompletion := NIL;
  439.                 ioNamePtr := NIL;
  440.                 ioVRefNum := VRefNum;
  441.                 ioWDDirID := ParamBlock^.ioDrDirID;
  442.                 ioWDProcID := 0;
  443.             END;
  444.         Err := PBOpenWD(WDBlock, False);
  445.  
  446.         IF Err <> NoErr THEN
  447.             ChangeDirectory := 0
  448.         ELSE
  449.             ChangeDirectory := WDBlock^.ioVRefNum;
  450.  
  451.         DisposPtr(Ptr(ParamBlock));
  452.  
  453.     END;
  454.  
  455.  
  456. FUNCTION FindParent (VRefNum: Integer; Levels: Integer): Integer;
  457. { From a given working directory, find working directory number for }
  458. { that directory. }
  459.  
  460.     VAR
  461.         ParamBlock: CInfoPBPtr;
  462.         WDBlock: WDPBPtr;
  463.         Err: OSErr;
  464.         i: Integer;
  465.         TheName: Str255;
  466.  
  467.     BEGIN
  468.  
  469.         ParamBlock := CInfoPBPtr(NewPtr(SizeOf(CInfoPBRec)));
  470.         WDBlock := WDPBPtr(NewPtr(SizeOf(WDPBRec)));
  471.  
  472.         Err := NoErr;
  473.         WITH WDBlock^ DO
  474.             BEGIN
  475.                 ioCompletion := NIL;
  476.                 ioNamePtr := NIL;
  477.                 ioVRefNum := VRefNum;
  478.                 ioWDIndex := 0;
  479.                 ioWDProcID := 0;
  480.             END;
  481.         Err := PBGetWDInfo(WDBlock, False);
  482.  
  483.         { Find directory ID }
  484.         ParamBlock^.ioDrParID := WDBlock^.ioWDDirID;
  485.         i := 1;
  486.         WHILE (Err = NoErr) AND (i <= (Levels + 1)) DO
  487.             BEGIN
  488.                 WITH ParamBlock^ DO
  489.                     BEGIN
  490.                         ioCompletion := NIL;
  491.                         ioNamePtr := NIL;
  492.                         ioVRefNum := VRefNum;
  493.                         ioDrDirID := 0;
  494.                         ioDirID := ioDrParID;  { We want the parent directory name }
  495.                         ioFVersNum := 0;
  496.                         ioFDirIndex := -1;  { Causes it to give information on ioDrDirID }
  497.                     END;
  498.                 Err := PBGetCatInfo(ParamBlock, False);
  499.                 i := i + 1;
  500.             END;
  501.  
  502.         { Open working directory }
  503.         WITH WDBlock^ DO
  504.             BEGIN
  505.                 ioCompletion := NIL;
  506.                 ioNamePtr := NIL;
  507.                 ioVRefNum := VRefNum;
  508.                 ioWDDirID := ParamBlock^.ioDrDirID;
  509.                 ioWDProcID := 0;
  510.             END;
  511.         Err := PBOpenWD(WDBlock, False);
  512.  
  513.         IF Err <> NoErr THEN
  514.             FindParent := 0
  515.         ELSE
  516.             FindParent := WDBlock^.ioVRefNum;
  517.  
  518.         DisposPtr(Ptr(ParamBlock));
  519.  
  520.     END;
  521.  
  522.  
  523. FUNCTION GetVRefNum (WorkingDir: Integer): Integer;
  524. { Take a working directory and convert it to a volume number }
  525.  
  526.     VAR
  527.         Ignore: Longint;
  528.         VRefNum: Integer;
  529.         Err: OSErr;
  530.  
  531.     BEGIN
  532.  
  533.         { GetWDInfo is a high level equivalent of the PB routine }
  534.         { but not documented in IM}
  535.         Err := GetWDInfo(WorkingDir, VRefNum, Ignore, Ignore);
  536.         GetVRefNum := VRefNum;
  537.  
  538.     END;
  539.  
  540.  
  541. FUNCTION GetCurWDRefNum: Integer;
  542. { Get the current system working directory }
  543.  
  544.     CONST
  545.         CurDirStore = $398;
  546.  
  547.     VAR
  548.         Pb: WDPBRec;
  549.         DirID: Longint;
  550.         Index: Integer;
  551.         Err: OSErr;
  552.  
  553.     BEGIN
  554.  
  555.         BlockMove(Ptr(CurDirStore), @DirID, 4);
  556.         Index := 1;
  557.         REPEAT
  558.             WITH Pb DO
  559.                 BEGIN
  560.                     ioCompletion := NIL;
  561.                     ioNamePtr := NIL;
  562.                     ioVRefNum := 0;
  563.                     ioWDIndex := Index;
  564.                     ioWDPROCID := 0;
  565.                     ioWDVRefNum := 0;
  566.                 END;
  567.             Err := PBGetWDInfo(@Pb, True);
  568.             Index := Index + 1;
  569.         UNTIL (Err <> NoErr) OR (DirID = PB.ioWDDirID);
  570.  
  571.         IF Err = NoErr THEN
  572.             GetCurWDRefNum := Pb.ioVRefNum
  573.         ELSE
  574.             GetCurWDRefNum := 0;
  575.  
  576.     END;
  577.  
  578.  
  579. PROCEDURE DrawFloppyDisk (Left, Top: Integer);
  580. { Draw floppy disk icon }
  581.  
  582.     BEGIN
  583.  
  584.         Moveto(Left + 5, Top + 2);
  585.         Lineto(Left + 14, Top + 2);
  586.         Lineto(Left + 16, Top + 4);
  587.         Lineto(Left + 16, Top + 13);
  588.         Lineto(Left + 5, Top + 13);
  589.  
  590.         Moveto(Left + 4, Top + 12);
  591.         Lineto(Left + 4, Top + 3);
  592.  
  593.         Moveto(Left + 13, Top + 3);
  594.         Lineto(Left + 13, Top + 5);
  595.  
  596.         Moveto(Left + 12, Top + 6);
  597.         Lineto(Left + 8, Top + 6);
  598.  
  599.         Moveto(Left + 7, Top + 5);
  600.         Lineto(Left + 7, Top + 3);
  601.  
  602.         Moveto(Left + 11, Top + 3);
  603.         Lineto(Left + 11, Top + 4);
  604.  
  605.  
  606.         Moveto(Left + 7, Top + 12);
  607.         Lineto(Left + 7, Top + 10);
  608.  
  609.         Moveto(Left + 8, Top + 9);
  610.         Lineto(Left + 12, Top + 9);
  611.  
  612.         Moveto(Left + 13, Top + 10);
  613.         Lineto(Left + 13, Top + 12);
  614.  
  615.     END;
  616.  
  617.  
  618. PROCEDURE DrawHardDrive (Left, Top: Integer);
  619. { Draw hard disk icon }
  620.  
  621.     BEGIN
  622.  
  623.         Moveto(Left + 3, Top + 6);
  624.         Lineto(Left + 3, Top + 9);
  625.  
  626.         Moveto(Left + 4, Top + 10);
  627.         Lineto(Left + 18, Top + 10);
  628.  
  629.         Moveto(Left + 19, Top + 9);
  630.         Lineto(Left + 19, Top + 6);
  631.  
  632.         Moveto(Left + 18, Top + 5);
  633.         Lineto(Left + 4, Top + 5);
  634.  
  635.         Moveto(Left + 5, Top + 8);
  636.         Lineto(Left + 5, Top + 8);
  637.  
  638.     END;
  639.  
  640.  
  641. PROCEDURE TrimVolumeName (Area: Rect; Offset: Integer; VAR TheVolume: Str255);
  642. { the volume name down to size and add a '...' }
  643.  
  644.     VAR
  645.         TheLength: Integer;
  646.         TrimmedVolume: Str255;
  647.  
  648.     BEGIN
  649.  
  650.         TheLength := (Area.Right - Area.Left) - Offset;
  651.         IF Thelength >= StringWidth(TheVolume) THEN
  652.             Exit(TrimVolumeName);
  653.         TrimmedVolume := Concat(Omit(TheVolume, Length(TheVolume), 1), CHR($C9));
  654.         WHILE StringWidth(TrimmedVolume) >= TheLength DO
  655.             BEGIN
  656.                 TrimmedVolume := Concat(Omit(TrimmedVolume, Length(TrimmedVolume) - 1, 2), CHR($C9));
  657.             END;
  658.         TheVolume := TrimmedVolume;
  659.  
  660.     END;
  661.  
  662.  
  663. PROCEDURE CSFVolumeBox.Draw (VAR Area: Rect);
  664.     Override;
  665. { Draw the icon and then the volume name }
  666.  
  667.     VAR
  668.         TheVolume: Str255;
  669.         VRefNum: Integer;
  670.         Err: OSErr;
  671.  
  672.     BEGIN
  673.  
  674.         EraseRect(Area);
  675.         Err := GetVol(@TheVolume, VRefNum);
  676.         IF CSFWindow(ItsEnclosure).CheckDrives THEN
  677.             BEGIN
  678.                 Err := GetVol(@TheVolume, VRefNum);
  679.                 { Check floppy drives }
  680.                 IF (CSFWindow(ItsEnclosure).fDrive1 = GetVRefNum(VRefNum)) OR (CSFWindow(ItsEnclosure).fDrive2 = GetVRefNum(VRefNum)) THEN
  681.                     DrawFloppyDisk(0, 0)
  682.                 ELSE
  683.                     DrawHardDrive(0, 0);
  684.             END
  685.         ELSE
  686.             DrawHardDrive(0, 0);
  687.         TrimVolumeName(Frame, 23, TheVolume);
  688.         Moveto(23, 12);
  689.         DrawString(TheVolume);
  690.  
  691.     END;
  692.  
  693.  
  694. PROCEDURE CSFVolumeBox.DoClick (hitPt: Point; modifierKeys: integer; when: longint);
  695.     Override;
  696.  { Change directory if clicked in }
  697.  
  698.     VAR
  699.         TheWindow: CSFWindow;
  700.         Temp: Integer;
  701.  
  702.     BEGIN
  703.  
  704.         { Step up one directory level }
  705.         TheWindow := CSFWindow(ItsEnclosure);
  706.         Temp := FindParent(TheWindow.fCurrentWD, 1);
  707.         IF Temp <> 0 THEN
  708.             BEGIN
  709.                 TheWindow.fCurrentWD := Temp;
  710.                 TheWindow.FillDialog(TheWindow.fCurrentWD);
  711.                 TheWindow.FindPath(TheWindow.fCurrentWD);
  712.                 CSFWindow(ItsEnclosure).DoStatus;
  713.             END;
  714.  
  715.         INHERITED DoClick(hitPt, modifierKeys, when);
  716.  
  717.     END;
  718.  
  719.  
  720. PROCEDURE CSFEditText.IEditText (anEnclosure: CView; aSupervisor: CBureaucrat; aWidth, aHeight, aHEncl, aVEncl: integer; aHSizing, aVSizing: SizingOption; aLineWidth: integer);
  721.     Override;
  722. { Initialize the text edit box }
  723.  
  724.     BEGIN
  725.  
  726.         INHERITED IEditText(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing, aLineWidth);
  727.  
  728.         { Override settext to insert different text }
  729.         SetText;
  730.  
  731.     END;
  732.  
  733.  
  734. PROCEDURE CSFEditText.DoKeyDown (theChar: char; keyCode: Byte; macEvent: EventRecord);
  735.     Override;
  736. { We have to intercept special keys to process them as clicks instead }
  737.  
  738.     BEGIN
  739.  
  740.         CASE keyCode OF
  741.             $24, $34:  { return or enter }
  742.                 DoCommand(kSaveButton);
  743.             $30:   { tab }
  744.                 DoCommand(kDriveButton);
  745.             OTHERWISE
  746.                 INHERITED DoKeyDown(theChar, keyCode, macEvent);
  747.         END;
  748.  
  749.         { Did we delete everything? }
  750.         IF IsEmpty THEN
  751.             BEGIN
  752.                 IF NOT fEmpty THEN
  753.                     BEGIN
  754.                         fEmpty := True;
  755.                         DoCommand(kEmptyText);
  756.                     END;
  757.             END
  758.         ELSE
  759.             BEGIN
  760.                 IF fEmpty THEN
  761.                     BEGIN
  762.                         fEmpty := False;
  763.                         DoCommand(kNonEmptyText);
  764.                     END;
  765.             END;
  766.  
  767.     END;
  768.  
  769.  
  770. FUNCTION CSFEditText.IsEmpty: Boolean;
  771. { Is the party over? }
  772.  
  773.     VAR
  774.         DataLength: Longint;
  775.  
  776.     BEGIN
  777.  
  778.         DataLength := macTE^^.teLength;
  779.         IF DataLength = 0 THEN
  780.             IsEmpty := True
  781.         ELSE
  782.             IsEmpty := False;
  783.  
  784.     END;
  785.  
  786.  
  787. PROCEDURE CSFEditText.SetText;
  788. { Set the initial text in the edit box }
  789.  
  790.     BEGIN
  791.  
  792.         fEmpty := False;
  793.         SetTextString('Untitled');
  794.         DoCommand(kNonEmptyText);
  795.  
  796.     END;
  797.  
  798.  
  799. PROCEDURE CSFEditText.Dawdle (VAR maxSleep: Longint);
  800.     Override;
  801. { Is the edit box empty for any other reason, then notify the dialog }
  802.  
  803.     BEGIN
  804.  
  805.         INHERITED Dawdle(maxSleep);
  806.  
  807.         IF IsEmpty THEN
  808.             BEGIN
  809.                 IF NOT fEmpty THEN
  810.                     BEGIN
  811.                         fEmpty := True;
  812.                         DoCommand(kEmptyText);
  813.                     END;
  814.             END
  815.         ELSE
  816.             BEGIN
  817.                 IF fEmpty THEN
  818.                     BEGIN
  819.                         fEmpty := False;
  820.                         DoCommand(kNonEmptyText);
  821.                     END;
  822.             END;
  823.  
  824.     END;
  825.  
  826.  
  827. PROCEDURE CSFEditText.SelectText;
  828. { Highlite everything }
  829.  
  830.     BEGIN
  831.  
  832.         TESetSelect(0, Maxint, macTe);
  833.  
  834.     END;
  835.  
  836.  
  837. FUNCTION CSFEditText.GetStr255: Str255;
  838. { Return a Pascal string of the first 255 characters }
  839.  
  840.     VAR
  841.         Temp: Str255;
  842.         DataLength: Longint;
  843.         TheCharsHandle: CharsHandle;
  844.  
  845.     BEGIN
  846.  
  847.         Temp := '';
  848.  
  849.         DataLength := macTE^^.teLength;
  850.         IF DataLength > 0 THEN
  851.             BEGIN
  852.                 IF DataLength > 255 THEN
  853.                     DataLength := 255;
  854.                 BlockMove(Ptr(Longint(@DataLength) + 3), @Temp, 1);
  855.  
  856.                 TheCharsHandle := GetTextHandle;
  857.                 HLock(Handle(TheCharsHandle));
  858.                 BlockMove(Ptr(TheCharsHandle^), Ptr(Longint(@Temp) + 1), DataLength);
  859.                 HUnLock(Handle(TheCharsHandle));
  860.             END;
  861.  
  862.         GetStr255 := Temp;
  863.  
  864.     END;
  865.  
  866.  
  867. PROCEDURE CSFWindow.ICSFWindow (TheDirector: CDirector);
  868. { Initialize the window. Do not override. }
  869.  
  870.     VAR
  871.         TheSize, ViewRect, DataBounds, TheRect: Rect;
  872.         CellSize: Point;
  873.         Err: OSErr;
  874.         TheText, TheName: Str255;
  875.         TheLength, h, v, TheWidth, TheCenter, Ignore: Integer;
  876.  
  877.     BEGIN
  878.  
  879.         { Init the window }
  880.         IWindow(9999, False, gDeskTop, TheDirector);
  881.         Prepare;
  882.         TextFont(SystemFont);
  883.         Move(100, 100);
  884.         SetTitle('Open');
  885.  
  886.         SetRect(TheSize, 0, 0, 70, kButtonHeight);
  887.  
  888.         { Create some buttons }
  889.         New(fEject);
  890.         fEject.IButton(KPushButton, Self, Self);
  891.         fEject.SetClickCmd(kEjectButton);
  892.         fEject.ChangeSize(TheSize, False);
  893.         fEject.SetTitle('Eject');
  894.         IF NOT CheckDrives THEN
  895.             fEject.Deactivate;
  896.         fEject.Show;
  897.  
  898.         New(fDrive);
  899.         fDrive.IButton(KPushButton, Self, Self);
  900.         fDrive.SetClickCmd(kDriveButton);
  901.         fDrive.ChangeSize(TheSize, False);
  902.         fDrive.SetTitle('Drive');
  903.         IF CountDrives = 1 THEN
  904.             fDrive.Deactivate;
  905.         fDrive.Show;
  906.  
  907.         New(fCancel);
  908.         fCancel.IButton(KPushButton, Self, Self);
  909.         fCancel.SetClickCmd(kCancelButton);
  910.         fCancel.ChangeSize(TheSize, False);
  911.         fCancel.SetTitle('Cancel');
  912.         fCancel.Show;
  913.  
  914.         { Create the main file box }
  915.         SetfViewRect;
  916.         SetRect(DataBounds, 0, 0, 1, 0);
  917.         SetPt(CellSize, 1000, 16);
  918.         ClipRect(GetMacPort^.PortRect);
  919.         fFileList := LNew(fViewRect, DataBounds, CellSize, 13000, GetMacPort, True, False, False, True);
  920.         fFileList^^.selFlags := lOnlyOne;
  921.         SetRect(fViewRect, fViewRect.Left, fViewRect.Top, fViewRect.Right + kScrollBarWidth, fViewRect.Bottom);
  922.         InsetRect(fViewRect, -1, -1);
  923.         FrameRect(fViewRect);
  924.         fCurrentWD := GetCurWDRefNum;
  925.  
  926.         { Fill the pull down menu }
  927.         Err := GetVol(@TheName, Ignore);
  928.         TheWidth := StringWidth(TheName) + 28;
  929.         TheCenter := (fViewRect.Right - fViewRect.Left + 16) DIV 2;
  930.         SetRect(fPathRect, TheCenter - (TheWidth DIV 2), fViewRect.Top - 23, TheCenter + (TheWidth DIV 2), fViewRect.Top - 7);
  931.         SetRect(DataBounds, 0, 0, 1, 0);
  932.         SetPt(CellSize, 1000, 16);
  933.         ClipRect(GetMacPort^.PortRect);
  934.         fPathList := LNew(fPathRect, DataBounds, CellSize, 13000, GetMacPort, True, False, False, False);
  935.         fPathList^^.LClikLoop := @ClickLoop;
  936.         ThePathList := fPathList;
  937.         FindPath(fCurrentWD);
  938.         FrameRect(fPathRect);
  939.         DropShadow(fPathRect);
  940.  
  941.         { Here is where your initializations occur }
  942.         MoreInitializations;
  943.  
  944.         New(fVolumeBox);
  945.         fVolumeBox.IPane(Self, Self, (MacPort^.PortRect.Right - 3) - (fViewRect.Right + 3), 16, fViewRect.Right + 3, fViewRect.Top, sizFIXEDLEFT, sizFIXEDTOP);
  946.         fVolumeBox.SetWantsClicks(True);
  947.         fVolumeBox.Show;
  948.  
  949.         fDriveIndex := 0;
  950.  
  951.         fGood := False;
  952.         fName := '';
  953.         fVName := '';
  954.  
  955.         { Show the window }
  956.         Select;
  957.  
  958.         fInitTime := True;
  959.     END;
  960.  
  961.  
  962. PROCEDURE CSFWindow.MoreInitializations;
  963. { Override me! }
  964.  
  965.     BEGIN
  966.  
  967.         { Does nothing }
  968.  
  969.     END;
  970.  
  971.  
  972. PROCEDURE CSFWindow.SetfViewRect;
  973. { Set the file box rect }
  974.  
  975.     BEGIN
  976.  
  977.         SetRect(fViewRect, 10, 30, 170, 158);
  978.  
  979.     END;
  980.  
  981.  
  982. PROCEDURE CSFWindow.DoKeyDown (theChar: char; keyCode: Byte; macEvent: EventRecord);
  983.     Override;
  984. { Intercept the tab key }
  985.  
  986.     BEGIN
  987.  
  988.         CASE keyCode OF
  989.             $30:  { tab }
  990.                 DoCommand(kDriveButton);
  991.             OTHERWISE
  992.                 INHERITED DoKeyDown(theChar, keyCode, macEvent);
  993.         END;
  994.  
  995.     END;
  996.  
  997.  
  998. PROCEDURE CSFWindow.DoCommand (TheCommand: Longint);
  999.     Override;
  1000. { Handle basic commands }
  1001.  
  1002.     BEGIN
  1003.  
  1004.         CASE (TheCommand) OF
  1005.             kCancelButton: 
  1006.                 DoCancel;
  1007.             kEjectButton: 
  1008.                 DoEject;
  1009.             kDriveButton: 
  1010.                 DoDrive;
  1011.             cmdDiskEvent: 
  1012.                 DoStatus;
  1013.             OTHERWISE
  1014.                 INHERITED DoCommand(TheCommand);
  1015.         END;
  1016.  
  1017.     END;
  1018.  
  1019.  
  1020. PROCEDURE CSFWindow.Update;
  1021.     Override;
  1022.  
  1023.     VAR
  1024.         savePort: GrafPtr;                { The current port                    }
  1025.         updateRect: Rect;                { Bounding box of update region        }
  1026.  
  1027.     BEGIN
  1028.  
  1029.         GetPort(savePort);                { Save the original port            }
  1030.         Prepare;
  1031.  
  1032.         BeginUpdate(macPort);            { Start the update process        }
  1033.                                         { This restricts the visible area    }
  1034.                                         {   to just the update region,        }
  1035.                                         {   meaning that no drawing will    }
  1036.                                         {   occur outside this region        }
  1037.  
  1038.         ClipRect(macPort^.portRect);        { Clip to the entire window        }
  1039.  
  1040.         { Your updates occur here }
  1041.         MoreUpdates;
  1042.  
  1043.         IF itsSubviews <> NIL THEN
  1044.             BEGIN                            { Draw all subviews                }
  1045.  
  1046.                 updateRect := macPort^.visRgn^^.rgnBBox;
  1047.                 itsSubviews.DoForEach1(Pane_Draw, @updateRect);
  1048.             END;
  1049.  
  1050.         EndUpdate(macPort);                { End the update process            }
  1051.         SetPort(savePort);                { Restore the original port        }
  1052.  
  1053.     END;
  1054.  
  1055.  
  1056. PROCEDURE CSFWindow.MoreUpdates;
  1057. { Override to do your updates }
  1058.  
  1059.     VAR
  1060.         TheRect: Rect;
  1061.  
  1062.     BEGIN
  1063.  
  1064.         { update the file box }
  1065.         LUpdate(macPort^.VisRgn, fFileList);
  1066.         FrameRect(fViewRect);
  1067.  
  1068.         { update the pull down menu }
  1069.         LUpdate(MacPort^.VisRgn, fPathList);
  1070.         FrameRect(fPathRect);
  1071.         DropShadow(fPathRect);
  1072.  
  1073.     END;
  1074.  
  1075.  
  1076. PROCEDURE CSFWindow.Free;
  1077.     Override;
  1078. { Dispose of the buttons and stuff }
  1079.  
  1080.     BEGIN
  1081.  
  1082.         fEject.Free;
  1083.         fDrive.Free;
  1084.         fCancel.Free;
  1085.         LDispose(fFileList);
  1086.         LDispose(fPathList);
  1087.         INHERITED Free;
  1088.  
  1089.     END;
  1090.  
  1091.  
  1092. PROCEDURE CSFWindow.Activate;
  1093.     Override;
  1094. { Set up globals and disable function keys }
  1095.  
  1096.     VAR
  1097.         TheCell: Cell;
  1098.  
  1099.     BEGIN
  1100.  
  1101.         INHERITED Activate;
  1102.  
  1103.         FKeyEnable(False);
  1104.         gGopher := Self;
  1105.         ThePathList := fPathList;
  1106.         FillDialog(fCurrentWD);
  1107.  
  1108.         { if theis a new window then select }
  1109.         IF fInitTime THEN
  1110.             BEGIN
  1111.                 SetPt(TheCell, 0, 0);
  1112.                 LSetSelect(True, TheCell, fFileList);
  1113.                 fInitTime := False
  1114.             END;
  1115.  
  1116.         DoStatus;
  1117.  
  1118.     END;
  1119.  
  1120.  
  1121. PROCEDURE CSFWindow.Deactivate;
  1122.     Override;
  1123. { Clean up after ourselves }
  1124.  
  1125.     BEGIN
  1126.  
  1127.         FKeyEnable(True);
  1128.         INHERITED Deactivate;
  1129.  
  1130.     END;
  1131.  
  1132.  
  1133. PROCEDURE CSFWindow.Close;
  1134.     Override;
  1135. { The party is over }
  1136.  
  1137.     BEGIN
  1138.  
  1139.         FKeyEnable(True);
  1140.         INHERITED Close;
  1141.  
  1142.     END;
  1143.  
  1144.  
  1145. FUNCTION CSFWindow.CountDrives: Integer;
  1146. { Count the number of mounted volumes }
  1147.  
  1148.     VAR
  1149.         Index, Count: Integer;
  1150.         Err: OSErr;
  1151.         PB: HParamBlockRec;
  1152.  
  1153.     BEGIN
  1154.  
  1155.         IF CheckDrives THEN
  1156.             ;
  1157.         Index := 0;
  1158.         Count := 0;
  1159.         Err := NoErr;
  1160.         WHILE Err <> nsvErr DO
  1161.             BEGIN
  1162.                 Index := Index + 1;
  1163.                 WITH PB DO
  1164.                     BEGIN
  1165.                         ioCompletion := NIL;
  1166.                         ioNamePtr := NIL;
  1167.                         ioVolIndex := Index;
  1168.                     END;
  1169.                 Err := PBHGetVInfo(@PB, False);
  1170.                 IF (PB.ioVDrvInfo = 0) AND NOT (Err = nsvErr) THEN
  1171.                     BEGIN
  1172.                         Err := NoErr;
  1173.                         Cycle;
  1174.                     END;
  1175.                 IF Err <> nsvErr THEN
  1176.                     Count := Count + 1;
  1177.             END;
  1178.         CountDrives := Count;
  1179.  
  1180.     END;
  1181.  
  1182.  
  1183. FUNCTION CSFWindow.GetNextVol: Integer;
  1184. { Find the next mounted volume }
  1185.  
  1186.     VAR
  1187.         Index: Integer;
  1188.         Err: OSErr;
  1189.         PB: HParamBlockRec;
  1190.  
  1191.     BEGIN
  1192.  
  1193.         IF CheckDrives THEN
  1194.             ;
  1195.         Index := fDriveIndex;
  1196.         Err := paramErr;
  1197.         WHILE Err <> NoErr DO
  1198.             BEGIN
  1199.                 Index := Index + 1;
  1200.                 WITH PB DO
  1201.                     BEGIN
  1202.                         ioCompletion := NIL;
  1203.                         ioNamePtr := NIL;
  1204.                         ioVolIndex := Index;
  1205.                     END;
  1206.                 Err := PBHGetVInfo(@PB, False);
  1207.                 IF (PB.ioVDrvInfo = 0) AND NOT (Err = nsvErr) THEN
  1208.                     BEGIN
  1209.                         Err := nsvErr;
  1210.                         Cycle;
  1211.                     END;
  1212.                 IF Err = nsvErr THEN
  1213.                     Index := 0;
  1214.             END;
  1215.         fDriveIndex := Index;
  1216.         GetNextVol := PB.ioVRefNum;
  1217.  
  1218.     END;
  1219.  
  1220.  
  1221. FUNCTION CSFWindow.CheckDrives: Boolean;
  1222. { Check the status of the floppy disk drives }
  1223.  
  1224.     VAR
  1225.         FreeBytes: Longint;
  1226.         Err, Ignore: OSErr;
  1227.         Index: Integer;
  1228.         Status: DrvSts;
  1229.  
  1230.     BEGIN
  1231.  
  1232.         CheckDrives := False;
  1233.  
  1234.         fDrive1 := 0;
  1235.         fDrive2 := 0;
  1236.         Err := DriveStatus(1, Status);
  1237.         IF (Status.Installed = 1) AND (Status.DiskInPlace <> 0) THEN
  1238.             Ignore := GetVInfo(1, NIL, fDrive1, FreeBytes);
  1239.  
  1240.         Err := DriveStatus(2, Status);
  1241.         IF (Status.Installed = 1) AND (Status.DiskInPlace <> 0) THEN
  1242.             Ignore := GetVInfo(2, NIL, fDrive2, FreeBytes);
  1243.  
  1244.         IF (fDrive1 <> 0) OR (fDrive2 <> 0) THEN
  1245.             CheckDrives := True;
  1246.  
  1247.     END;
  1248.  
  1249.  
  1250. PROCEDURE CSFWindow.DoEject;
  1251. { Eject a floppy disk }
  1252.  
  1253.     VAR
  1254.         WorkingDir: Integer;
  1255.         b: boolean;
  1256.  
  1257.     BEGIN
  1258.  
  1259.  
  1260.         IF fDriveIndex <> 1 THEN
  1261.             BEGIN
  1262.                 b := gError.CheckOSError(Eject(NIL, fCurrentWD));
  1263.                 fCurrentWD := GetNextVol;
  1264.                 FillDialog(fCurrentWD);
  1265.                 FindPath(fCurrentWD);
  1266.                 DoStatus;
  1267.             END;
  1268.  
  1269.     END;
  1270.  
  1271.  
  1272. PROCEDURE CSFWindow.DoDrive;
  1273. { Change drives }
  1274.  
  1275.     BEGIN
  1276.  
  1277.         IF fDrive.IsActive THEN
  1278.             BEGIN
  1279.                 fCurrentWD := GetNextVol;
  1280.                 FillDialog(fCurrentWD);
  1281.                 FindPath(fCurrentWD);
  1282.                 DoStatus;
  1283.             END;
  1284.  
  1285.     END;
  1286.  
  1287.  
  1288. PROCEDURE CSFWindow.DoCancel;
  1289. { Close the window }
  1290. { Override this method to cancel your operations }
  1291.  
  1292.     BEGIN
  1293.  
  1294.         Close;
  1295.  
  1296.     END;
  1297.  
  1298.  
  1299. PROCEDURE CSFWindow.DoStatus;
  1300. { Bring buttons upto date }
  1301.  
  1302.     VAR
  1303.         Err: OSErr;
  1304.         VRefNum: Integer;
  1305.  
  1306.     BEGIN
  1307.  
  1308.         { more than one volume mounted }
  1309.         IF CountDrives > 1 THEN
  1310.             fDrive.Activate
  1311.         ELSE
  1312.             fDrive.Deactivate;
  1313.  
  1314.         { Ejectable disks in place }
  1315.         IF CheckDrives THEN
  1316.             BEGIN
  1317.                 IF (GetVRefNum(fCurrentWD) = fDrive1) OR (GetVRefNum(fCurrentWD) = fDrive2) THEN
  1318.                     fEject.Activate
  1319.                 ELSE
  1320.                     fEject.Deactivate;
  1321.             END
  1322.         ELSE
  1323.             BEGIN
  1324.                 fEject.Deactivate;
  1325.             END;
  1326.  
  1327.         fVolumeBox.Refresh;
  1328.  
  1329.     END;
  1330.  
  1331.  
  1332. PROCEDURE CSFWindow.DoClick (hitPt: Point; modifierKeys: integer; when: longint);
  1333.     Override;
  1334. { Handle clicks in the file box and the puldown menu }
  1335.  
  1336.     VAR
  1337.         b: Boolean;
  1338.         TheCell: Cell;
  1339.         TheLength: Integer;
  1340.         TheDirectory, TheName: Str255;
  1341.         TheRect: Rect;
  1342.         TheSelection: Str255;
  1343.         Temp: Integer;
  1344.         Err: OSErr;
  1345.  
  1346.     BEGIN
  1347.  
  1348.         { Click in file box? }
  1349.         IF PtInRect(hitPt, fViewRect) THEN
  1350.             BEGIN
  1351.                 Prepare;
  1352.                 ClipRect(MacPort^.PortRect);
  1353.                 B := LClick(hitPt, modifierKeys, fFileList);
  1354.                 TheSelection := FindSelection;
  1355.                 { Inactive }
  1356.                 IF TheSelection[1] = '-' THEN
  1357.                     BEGIN
  1358.                         SetPt(TheCell, 0, 0);
  1359.                         IF LGetSelect(True, TheCell, fFileList) THEN
  1360.                             BEGIN
  1361.                                 LSetSelect(False, TheCell, fFileList);
  1362.                                 DoStatus;
  1363.                             END;
  1364.                     END
  1365.                 { Open the file of directory }
  1366.                 ELSE IF (gClicks > 1) THEN
  1367.                     BEGIN
  1368.                         IF TheSelection[1] = '+' THEN
  1369.                             BEGIN
  1370.                                 IF TheSelection[2] = '@' THEN
  1371.                                     BEGIN
  1372.                                         { Directory }
  1373.                                         fCurrentWD := ChangeDirectory(fCurrentWD, Omit(TheSelection, 1, 2));
  1374.                                         FillDialog(fCurrentWD);
  1375.                                         FindPath(fCurrentWD);
  1376.                                         DoStatus;
  1377.                                     END
  1378.                                 ELSE
  1379.                                     BEGIN
  1380.                                         { File }
  1381.                                         fGood := True;
  1382.                                         fName := Omit(TheSelection, 1, 2);
  1383.                                         Err := GetVol(@fVName, Temp);
  1384.                                         DoCommand(kSelection);
  1385.                                     END;
  1386.                             END;
  1387.                     END;
  1388.             END;
  1389.  
  1390.         { Pull down menu }
  1391.         IF PtInRect(hitPt, fPathRect) THEN
  1392.             BEGIN
  1393.                 Prepare;
  1394.                 ClipRect(MacPort^.PortRect);
  1395.                 LSize(fMenuWidth, fMenuHeight, fPathList);
  1396.                 fPathRect := fPathList^^.rView;
  1397.                 InsetRect(fPathRect, -1, -1);
  1398.                 EraseRect(fPathRect);
  1399.                 FrameRect(fPathRect);
  1400.                 DropShadow(fPathRect);
  1401.                 LUpdate(MacPort^.VisRgn, fPathList);
  1402.                 B := LClick(hitPt, modifierKeys, fPathList);
  1403.  
  1404.                 LSetSelect(False, ThePathCell, fPathList);
  1405.  
  1406.                 IF ThePathCell.v > 0 THEN
  1407.                     BEGIN
  1408.                         { Move up directory tree }
  1409.                         fCurrentWD := FindParent(fCurrentWD, ThePathCell.v);
  1410.                         FillDialog(fCurrentWD);
  1411.                         FindPath(fCurrentWD);
  1412.                     END
  1413.                 ELSE
  1414.                     BEGIN
  1415.                         SetPathRect;
  1416.                     END;
  1417.             END;
  1418.  
  1419.         INHERITED DoClick(hitPt, modifierKeys, when);
  1420.  
  1421.     END;
  1422.  
  1423.  
  1424. FUNCTION CSFWindow.FileFilter (ParamBlock: CInfoPBPtr): Boolean;
  1425. { Filter out unwanted files from showing in the file box }
  1426.  
  1427.     BEGIN
  1428.  
  1429.         { False means to show the file }
  1430.         FileFilter := False;
  1431.  
  1432.     END;
  1433.  
  1434.  
  1435. FUNCTION CSFWindow.ActiveFilter (ParamBlock: CInfoPBPtr): Boolean;
  1436. { Activate the file--not grayed out }
  1437.  
  1438.     BEGIN
  1439.  
  1440.         ActiveFilter := True;
  1441.  
  1442.     END;
  1443.  
  1444.  
  1445. PROCEDURE CSFWindow.FillDialog (VRefNum: Integer);
  1446. { Read the directory and fill the file box }
  1447.  
  1448.     VAR
  1449.         Err: OSErr;
  1450.         Count, Index: Integer;
  1451.         TheTitle: Str255;
  1452.         ParamBlock: CInfoPBPtr;
  1453.         TheName: Str255;
  1454.         TheCell: Cell;
  1455.  
  1456.     BEGIN
  1457.  
  1458.         Err := SetVol(NIL, VRefNum);
  1459.         ParamBlock := CInfoPBPtr(NewPtr(SizeOf(CInfoPBRec)));
  1460.         Index := 1;
  1461.         TheCell.h := 0;
  1462.         Err := NoErr;
  1463.         LDoDraw(False, fFileList);
  1464.         LDelRow(0, 0, fFileList);
  1465.         WHILE (Err = NoErr) DO
  1466.             BEGIN
  1467.                 TheName := '';
  1468.                 WITH ParamBlock^ DO
  1469.                     BEGIN
  1470.                         ioCompletion := NIL;
  1471.                         ioNamePtr := @TheName;
  1472.                         ioVRefNum := VRefNum;
  1473.                         ioDirID := 0;
  1474.                         ioDrDirID := 0;
  1475.                         ioFVersNum := 0;
  1476.                         ioFDirIndex := Index;
  1477.                     END;
  1478.                 Err := PBGetCatInfo(ParamBlock, False);
  1479.                 IF (Err = fnfErr) THEN
  1480.                     Leave;
  1481.                 IF Err <> NoErr THEN
  1482.                     BEGIN
  1483.                         { Ka-Boom }
  1484.                         Index := RedAlert(kSystemError);
  1485.                         Leave;
  1486.                     END;
  1487.                 { Include file or directory? }
  1488.                 IF FileFilter(ParamBlock) THEN
  1489.                     BEGIN
  1490.                         Cycle;
  1491.                     END;
  1492.                 { Is it a directory }
  1493.                 IF IsDirectory(ParamBlock) THEN
  1494.                     BEGIN
  1495.                         TheName := Concat('@', TheName);
  1496.                     END
  1497.                 ELSE
  1498.                     BEGIN
  1499.                         IF ParamBlock^.ioFlFndrInfo.fdType = 'APPL' THEN
  1500.                             TheName := Concat('#', TheName)
  1501.                         ELSE
  1502.                             TheName := Concat('!', TheName);
  1503.                     END;
  1504.                 { Grayed? }
  1505.                 IF ActiveFilter(ParamBlock) THEN
  1506.                     BEGIN
  1507.                         { Activate }
  1508.                         TheName := Concat('+', TheName);
  1509.                     END
  1510.                 ELSE
  1511.                     BEGIN
  1512.                         { Dectivate }
  1513.                         TheName := Concat('-', TheName);
  1514.                     END;
  1515.                 { Stuff it }
  1516.                 TheCell.v := LAddRow(1, Maxint, fFileList);
  1517.                 LSetCell(Ptr(@TheName[1]), Length(TheName), TheCell, fFileList);
  1518.                 Index := Index + 1;
  1519.             END;
  1520.         LDoDraw(True, fFileList);
  1521.         Prepare;
  1522.         ClipRect(GetMacPort^.PortRect);
  1523.         EraseRect(fFileList^^.rView);
  1524.         LUpdate(MacPort^.VisRgn, fFileList);
  1525.         DisposPtr(Ptr(ParamBlock));
  1526.  
  1527.     END;
  1528.  
  1529.  
  1530. PROCEDURE CSFWindow.SetPathRect;
  1531. { Find the pull down menu rect }
  1532.  
  1533.     VAR
  1534.         TheString, TheDirectory: Str255;
  1535.         TheCell: Cell;
  1536.         TheLength: Integer;
  1537.         TheRect: Rect;
  1538.  
  1539.     BEGIN
  1540.  
  1541.         { Out with the old }
  1542.         TheRect := fPathRect;
  1543.         InsetRect(TheRect, -1, -1);
  1544.         EraseRect(TheRect);
  1545.         InvalRect(TheRect);
  1546.  
  1547.         SetPt(TheCell, 0, 0);
  1548.         IF LGetSelect(True, TheCell, fPathList) THEN
  1549.             ;
  1550.         TheDirectory := GetCellContents(TheCell, fPathList);
  1551.         TheLength := StringWidth(TheDirectory) + 28;
  1552.         LSize(TheLength, fPathList^^.CellSize.v, fPathList);
  1553.         fPathList^^.rView.Left := (((fViewRect.Right - fViewRect.Left + 16) DIV 2) + fViewRect.Left) - (TheLength DIV 2);
  1554.         fPathList^^.rView.Right := fPathList^^.rView.Left + TheLength;
  1555.         fPathRect := fPathList^^.rView;
  1556.  
  1557.         SetPt(TheCell, 0, 0);
  1558.         TheString := GetCellContents(TheCell, fPathList);
  1559.         TheString := Omit(TheString, 1, 2);
  1560.         TheLength := StringWidth(TheString);
  1561.  
  1562.         fPathRect := fPathList^^.rView;
  1563.         fPathRect.Right := fPathRect.Left + TheLength + 28;
  1564.         InsetRect(fPathRect, -1, -1);
  1565.  
  1566.         { In with the new }
  1567.         InvalRect(TheRect);
  1568.         TheRect := fPathRect;
  1569.         InsetRect(TheRect, -1, -1);
  1570.         InvalRect(TheRect);
  1571.         EraseRect(TheRect);
  1572.         Update;
  1573.  
  1574.     END;
  1575.  
  1576.  
  1577. PROCEDURE CSFWindow.FindPath (VRefNum: Integer);
  1578. { Fill the pull down menu }
  1579.  
  1580.     VAR
  1581.         ParamBlock: CInfoPBPtr;
  1582.         TheName, LastName: Str255;
  1583.         Err: OSErr;
  1584.         TheCell: Cell;
  1585.         TheWidth, PathWidth, Ignore: Integer;
  1586.         FirstWidth: Boolean;
  1587.  
  1588.     BEGIN
  1589.  
  1590.         IF VRefNum = 0 THEN
  1591.             Err := GetVol(NIL, VRefNum);
  1592.  
  1593.         Err := SetVol(NIL, VRefNum);
  1594.  
  1595.         LastName := '';
  1596.         FirstWidth := True;
  1597.  
  1598.         fMenuWidth := 0;
  1599.         fMenuHeight := 0;
  1600.  
  1601.         { Clear the List }
  1602.         LDoDraw(False, fPathList);
  1603.         LDelRow(0, 0, fPathList);
  1604.  
  1605.         ParamBlock := CInfoPBPtr(NewPtr(SizeOf(CInfoPBRec)));
  1606.  
  1607.         WITH ParamBlock^ DO
  1608.             BEGIN
  1609.                 ioCompletion := NIL;
  1610.                 ioNamePtr := NIL;
  1611.                 ioVRefNum := VRefNum;
  1612.                 ioDirID := 0;
  1613.                 ioFVersNum := 0;
  1614.                 ioFDirIndex := 0;
  1615.             END;
  1616.         Err := PBGetCatInfo(ParamBlock, False);
  1617.  
  1618.         Err := NoErr;
  1619.         WHILE Err = NoErr DO
  1620.             BEGIN
  1621.                 TheName := '';
  1622.                 WITH ParamBlock^ DO
  1623.                     BEGIN
  1624.                         ioCompletion := NIL;
  1625.                         ioNamePtr := @TheName;
  1626.                         ioVRefNum := VRefNum;
  1627.                         ioDirID := 0;
  1628.                         ioDrDirID := ioDrParID;  { We want the parent directory name }
  1629.                         ioFVersNum := 0;
  1630.                         ioFDirIndex := -1;  { Causes it to give information on ioDrDirID }
  1631.                     END;
  1632.                 Err := PBGetCatInfo(ParamBlock, False);
  1633.                 IF Err = NoErr THEN
  1634.                     BEGIN
  1635.                         { Determine a length and compare it, if it is larger then store the value }
  1636.                         TheWidth := StringWidth(TheName) + 28;
  1637.                         IF FirstWidth THEN
  1638.                             BEGIN
  1639.                                 FirstWidth := False;
  1640.                                 PathWidth := TheWidth;
  1641.                             END;
  1642.  
  1643.                         IF TheWidth > fMenuWidth THEN
  1644.                             fMenuWidth := TheWidth;
  1645.  
  1646.                         LastName := TheName;
  1647.  
  1648.                         { Add a new row to the list }
  1649.                         TheName := Concat('+$', TheName);
  1650.                         TheCell.h := 0;
  1651.                         TheCell.v := LAddRow(1, Maxint, fPathList);
  1652.                         LSetCell(Ptr(@TheName[1]), Length(TheName), TheCell, fPathList);
  1653.  
  1654.                         { Increment the height }
  1655.                         fMenuHeight := fMenuHeight + 16;
  1656.                     END
  1657.                 ELSE
  1658.                     BEGIN
  1659.                         { Change the icon of the last item }
  1660.                         IF LastName <> '' THEN
  1661.                             BEGIN
  1662.                                 Ignore := GetVol(NIL, VRefNum);
  1663.                                 IF CheckDrives THEN
  1664.                                     BEGIN
  1665.                                         IF (fDrive1 = GetVRefNum(VRefNum)) OR (fDrive2 = GetVRefNum(VRefNum)) THEN
  1666.                                             TheName := Concat('+^', LastName)
  1667.                                         ELSE
  1668.                                             TheName := Concat('+%', LastName);
  1669.                                     END
  1670.                                 ELSE
  1671.                                     TheName := Concat('+%', LastName);
  1672.                                 LSetCell(Ptr(@TheName[1]), Length(TheName), TheCell, fPathList);
  1673.                             END
  1674.                         ELSE
  1675.                             sysbeep(1);
  1676.                     END;
  1677.             END;
  1678.  
  1679.         IF fMenuHeight >= (MacPort^.PortRect.Bottom - fPathRect.Top - 10) THEN
  1680.             fMenuHeight := ((MacPort^.PortRect.Bottom - fPathRect.Top - 10) DIV 16) * 16;
  1681.  
  1682.         InsetRect(fPathRect, -1, -1);
  1683.         EraseRect(fPathRect);
  1684.         LSize(fMenuWidth, 16, fPathList);
  1685.         LDoDraw(True, fPathList);
  1686.         SetPathRect;
  1687.         FrameRect(fPathRect);
  1688.         DropShadow(fPathRect);
  1689.  
  1690.         DisposPtr(Ptr(ParamBlock));
  1691.  
  1692.     END;
  1693.  
  1694.  
  1695. FUNCTION CSFWindow.FindSelection: Str255;
  1696. { Find the first selected item in the file box }
  1697.  
  1698.     VAR
  1699.         TheCell: Cell;
  1700.  
  1701.     BEGIN
  1702.  
  1703.         SetPt(TheCell, 0, 0);
  1704.         IF LGetSelect(True, TheCell, fFileList) THEN
  1705.             FindSelection := GetCellContents(TheCell, fFileList)
  1706.         ELSE
  1707.             FindSelection := '';
  1708.  
  1709.     END;
  1710.  
  1711.  
  1712. PROCEDURE CSFWindow.DoSelection;
  1713. { Set up the SFReply }
  1714.  
  1715.     VAR
  1716.         TheReply: SFReply;
  1717.         FndrInfo: FInfo;
  1718.         Err: OSErr;
  1719.  
  1720.     BEGIN
  1721.  
  1722.         { Set up the reply }
  1723.         WITH TheReply DO
  1724.             BEGIN
  1725.                 Good := fGood;
  1726.                 Copy := False;
  1727.                 Err := GetFInfo(Self.fName, fCurrentWD, FndrInfo);
  1728.                 fType := FndrInfo.fdType;
  1729.                 vRefNum := fCurrentWD;
  1730.                 Version := 0;
  1731.                 fName := Self.fName;
  1732.             END;
  1733.  
  1734.         FileSelected(TheReply);
  1735.  
  1736.     END;
  1737.  
  1738.  
  1739. PROCEDURE CSFWindow.FileSelected (TheReply: SFReply);
  1740. { Override me!!!!!!!!!  This where you handle the reply. }
  1741.  
  1742.     BEGIN
  1743.  
  1744.         Sysbeep(1);
  1745.  
  1746.     END;
  1747.  
  1748.  
  1749. FUNCTION CSFWindow.RedAlert (AlertID: Integer): Integer;
  1750. { Display error alerts }
  1751.  
  1752.     CONST
  1753.         kAlertOffset = 15;
  1754.  
  1755.     TYPE
  1756.         AlertTHndl = ^AlertTPtr;
  1757.         AlertTPtr = ^AlertTemplate;
  1758.  
  1759.     VAR
  1760.         TheAlert: AlertTHndl;
  1761.         TheAlertRect, TheRect, TheBounds, TheFrame: Rect;
  1762.         ThePoint: Point;
  1763.  
  1764.     BEGIN
  1765.  
  1766.         { Get the alert }
  1767.         TheAlert := AlertTHndl(GetResource('ALRT', AlertID));
  1768.         HNoPurge(Handle(TheAlert));
  1769.  
  1770.         { Move the alert }
  1771.         TheAlertRect := TheAlert^^.boundsRect;
  1772.         gDeskTop.GetBounds(TheBounds);
  1773.         TheFrame := MacPort^.PortRect;
  1774.         LocalToGlobal(TheFrame.TopLeft);
  1775.         LocalToGlobal(TheFrame.BotRight);
  1776.         IF SectRect(TheBounds, TheFrame, TheRect) THEN
  1777.             BEGIN
  1778.                 ThePoint.v := TheRect.Bottom - TheAlertRect.Bottom - kAlertOffset;
  1779.                 ThePoint.h := TheRect.Left + kAlertOffset;
  1780.                 IF NOT PtInRect(ThePoint, TheBounds) THEN
  1781.                     BEGIN
  1782.                         IF ThePoint.v < TheBounds.Left THEN
  1783.                             ThePoint.v := TheBounds.Left;
  1784.                         IF ThePoint.h < TheBounds.Top THEN
  1785.                             ThePoint.h := TheBounds.Top;
  1786.                     END;
  1787.                 SetRect(TheAlertRect, ThePoint.h, ThePoint.v, ThePoint.h + TheAlert^^.boundsRect.Right, ThePoint.v + TheAlert^^.boundsRect.Bottom);
  1788.                 IF TheAlertRect.Right > TheBounds.Right THEN
  1789.                     BEGIN
  1790.                         TheAlertRect.Left := TheAlertRect.Left - (TheAlertRect.Right - TheBounds.Right);
  1791.                         TheAlertRect.Right := TheAlertRect.Left + (TheAlertRect.Right - TheBounds.Right);
  1792.                     END;
  1793.                 IF TheAlertRect.Bottom > TheBounds.Bottom THEN
  1794.                     BEGIN
  1795.                         TheAlertRect.Top := TheAlertRect.Top - (TheAlertRect.Bottom - TheBounds.Bottom);
  1796.                         TheAlertRect.Bottom := TheAlertRect.Top + (TheAlertRect.Bottom - TheBounds.Bottom);
  1797.                     END;
  1798.             END
  1799.         ELSE
  1800.             BEGIN
  1801.                 SetRect(TheAlertRect, TheAlertRect.Left + 100, TheAlertRect.Top + 100, TheAlertRect.Right + 100, TheAlertRect.Bottom + 100);
  1802.             END;
  1803.  
  1804.         { Display the alert }
  1805.         TheAlert^^.boundsRect := TheAlertRect;
  1806.         RedAlert := Alert(AlertID, NIL);
  1807.         HPurge(Handle(TheAlert));
  1808.         ReleaseResource(Handle(TheAlert));
  1809.  
  1810.     END;
  1811.  
  1812.  
  1813. PROCEDURE CSFGetWindow.MoreInitializations;
  1814.     Override;
  1815. { Follow this example to do your initializations }
  1816.  
  1817.     VAR
  1818.         TheSize: Rect;
  1819.  
  1820.     BEGIN
  1821.  
  1822.         fEject.Offset(kGetButtonOffset, 76, True);
  1823.         fDrive.Offset(kGetButtonOffset, 101, True);
  1824.         fCancel.Offset(kGetButtonOffset, 171, True);
  1825.  
  1826.         SetRect(TheSize, 0, 0, 70, kButtonHeight);
  1827.  
  1828.         New(fOpen);
  1829.         fOpen.IButton(KPushButton, Self, Self);
  1830.         fOpen.SetClickCmd(kOpenButton);
  1831.         fOpen.ChangeSize(TheSize, False);
  1832.         fOpen.Offset(kGetButtonOffset, 146, False);
  1833.         fOpen.SetTitle('Open');
  1834.         fOpen.Deactivate;
  1835.         fOpen.Show;
  1836.  
  1837.         ChangeSize(363, 215);
  1838.  
  1839.     END;
  1840.  
  1841.  
  1842. PROCEDURE CSFGetWindow.DoKeyDown (theChar: char; keyCode: Byte; macEvent: EventRecord);
  1843.     Override;
  1844. { Special key handling }
  1845.  
  1846.     BEGIN
  1847.  
  1848.         CASE keyCode OF
  1849.             $24, $34: 
  1850.                 DoCommand(kOpenButton);
  1851.             OTHERWISE
  1852.                 INHERITED DoKeyDown(theChar, keyCode, macEvent);
  1853.         END;
  1854.  
  1855.     END;
  1856.  
  1857.  
  1858. PROCEDURE CSFGetWindow.SetfViewRect;
  1859.     Override;
  1860. { Resize the file box }
  1861.  
  1862.     BEGIN
  1863.  
  1864.         SetRect(fViewRect, 20, 47, 237 - kScrollBarWidth, 47 + (9 * 16));
  1865.  
  1866.     END;
  1867.  
  1868.  
  1869. PROCEDURE CSFGetWindow.DoCommand (TheCommand: Longint);
  1870.     Override;
  1871. { Do the commands for this subclass }
  1872.  
  1873.     BEGIN
  1874.  
  1875.         CASE TheCommand OF
  1876.             kOpenButton: 
  1877.                 DoOpen;
  1878.             kSelection: 
  1879.                 DoSelection;
  1880.             OTHERWISE
  1881.                 INHERITED DoCommand(TheCommand);
  1882.         END;
  1883.  
  1884.     END;
  1885.  
  1886.  
  1887. PROCEDURE CSFGetWindow.MoreUpdates;
  1888.     Override;
  1889. { Add our updates }
  1890.  
  1891.     BEGIN
  1892.  
  1893.         INHERITED MoreUpdates;
  1894.  
  1895.         PenPat(Gray);
  1896.         Moveto(260, 132);
  1897.         Lineto(338, 132);
  1898.         PenNormal;
  1899.  
  1900.     END;
  1901.  
  1902.  
  1903. PROCEDURE CSFGetWindow.DoStatus;
  1904.     Override;
  1905. { Add the open button to the status logic }
  1906.  
  1907.     VAR
  1908.         TheCell: Cell;
  1909.  
  1910.     BEGIN
  1911.  
  1912.         INHERITED DoStatus;
  1913.  
  1914.         SetPt(TheCell, 0, 0);
  1915.         IF LGetSelect(True, TheCell, fFileList) THEN
  1916.             BEGIN
  1917.                 fOpen.Activate;
  1918.             END
  1919.         ELSE
  1920.             BEGIN
  1921.                 fOpen.Deactivate;
  1922.             END;
  1923.  
  1924.     END;
  1925.  
  1926.  
  1927. PROCEDURE CSFGetWindow.DoClick (hitPt: Point; modifierKeys: integer; when: longint);
  1928.     Override;
  1929. { Make sure we have the correct file selected }
  1930.  
  1931.     VAR
  1932.         TheCell: Cell;
  1933.         SaveDirectory: Integer;
  1934.  
  1935.     BEGIN
  1936.  
  1937.         SaveDirectory := fCurrentWD;
  1938.  
  1939.         INHERITED DoClick(hitPt, modifierKeys, when);
  1940.  
  1941.         IF (SaveDirectory <> fCurrentWD) AND (fFileList^^.dataBounds.Bottom > 0) THEN
  1942.             BEGIN
  1943.                 Prepare;
  1944.                 ClipRect(MacPort^.PortRect);
  1945.                 SetPt(TheCell, 0, 0);
  1946.                 LSetSelect(True, TheCell, fFileList);
  1947.             END;
  1948.  
  1949.         SetPt(TheCell, 0, 0);
  1950.         IF LGetSelect(True, TheCell, fFileList) THEN
  1951.             BEGIN
  1952.                 fOpen.Activate;
  1953.             END
  1954.         ELSE
  1955.             BEGIN
  1956.                 fOpen.Deactivate;
  1957.             END;
  1958.  
  1959.     END;
  1960.  
  1961.  
  1962. PROCEDURE CSFGetWindow.Free;
  1963.     Override;
  1964. { Get rid of the open button }
  1965.  
  1966.     BEGIN
  1967.  
  1968.         fOpen.Free;
  1969.  
  1970.         INHERITED Free;
  1971.  
  1972.     END;
  1973.  
  1974.  
  1975. PROCEDURE CSFGetWindow.DoOpen;
  1976. { Respond to the open button }
  1977.  
  1978.     VAR
  1979.         TheRect: Rect;
  1980.         TheSelection: Str255;
  1981.         TheCell: Cell;
  1982.         Temp: Integer;
  1983.         Err: OSErr;
  1984.  
  1985.     BEGIN
  1986.  
  1987.         IF fOpen.IsActive THEN
  1988.             BEGIN
  1989.                 TheSelection := FindSelection;
  1990.                 IF TheSelection[1] = '+' THEN
  1991.                     BEGIN
  1992.                         IF TheSelection[2] = '@' THEN
  1993.                             BEGIN
  1994.                                 { Directory selected }
  1995.                                 fCurrentWD := ChangeDirectory(fCurrentWD, Omit(TheSelection, 1, 2));
  1996.                                 FillDialog(fCurrentWD);
  1997.                                 FindPath(fCurrentWD);
  1998.                                 TheRect := fPathRect;
  1999.                                 InsetRect(TheRect, -1, -1);
  2000.                                 InvalRect(TheRect);
  2001.                                 EraseRect(TheRect);
  2002.                                 Update;
  2003.                                 DoStatus;
  2004.  
  2005.                                 Prepare;
  2006.                                 ClipRect(MacPort^.PortRect);
  2007.                                 SetPt(TheCell, 0, 0);
  2008.                                 LSetSelect(True, TheCell, fFileList);
  2009.                                 IF LGetSelect(True, TheCell, fFileList) THEN
  2010.                                     fOpen.Activate;
  2011.                             END
  2012.                         ELSE
  2013.                             BEGIN
  2014.                                 { File selected }
  2015.                                 fGood := True;
  2016.                                 fName := Omit(TheSelection, 1, 2);
  2017.                                 Err := GetVol(@fVName, Temp);
  2018.                                 DoCommand(kSelection);
  2019.                             END;
  2020.                     END;
  2021.             END;
  2022.  
  2023.     END;
  2024.  
  2025.  
  2026. PROCEDURE CSFSaveWindow.MoreInitializations;
  2027.     Override;
  2028. { Move existing buttons and add the save button and edit box }
  2029.  
  2030.     VAR
  2031.         TheSize: Rect;
  2032.  
  2033.     BEGIN
  2034.  
  2035.         fEject.Offset(kSaveButtonOffset, 64, True);
  2036.         fDrive.Offset(kSaveButtonOffset, 90, True);
  2037.         fCancel.Offset(kSaveButtonOffset, 166, True);
  2038.  
  2039.         SetRect(TheSize, 0, 0, 70, kButtonHeight);
  2040.  
  2041.         New(fSave);
  2042.         fSave.IButton(KPushButton, Self, Self);
  2043.         fSave.SetClickCmd(kSaveButton);
  2044.         fSave.ChangeSize(TheSize, False);
  2045.         fSave.Offset(kSaveButtonOffset, 140, False);
  2046.         fSave.SetTitle('Save');
  2047.         fSave.Deactivate;
  2048.         fSave.Show;
  2049.  
  2050.         fPromptString := 'Save file as…';
  2051.  
  2052.         New(fFileName);
  2053.         fFileName.IEditText(Self, Self, fViewRect.Right - fViewRect.Left - 4, 16, fViewRect.Left + 2, fViewRect.Bottom + 30, sizFIXEDLEFT, sizFIXEDTOP, -1);
  2054.         fFileName.SelectText;
  2055.         fFileName.Show;
  2056.  
  2057.         ChangeSize(319, 199);
  2058.         SetTitle('Save');
  2059.  
  2060.  
  2061.     END;
  2062.  
  2063.  
  2064. PROCEDURE CSFSaveWindow.SetfViewRect;
  2065.     Override;
  2066. { Move the file box }
  2067.  
  2068.     BEGIN
  2069.  
  2070.         SetRect(fViewRect, 22, 37, 204 - kScrollBarWidth, 37 + (6 * 16));
  2071.  
  2072.     END;
  2073.  
  2074.  
  2075. FUNCTION CSFSaveWindow.ActiveFilter (ParamBlock: CInfoPBPtr): Boolean;
  2076.     Override;
  2077. { Only activate directories }
  2078.  
  2079.     BEGIN
  2080.  
  2081.         IF ParamBlock^.ioFlFndrInfo.fdType = 'APPL' THEN
  2082.             BEGIN
  2083.                 ActiveFilter := False;
  2084.                 Exit(ActiveFilter);
  2085.             END;
  2086.  
  2087.         IF IsDirectory(ParamBlock) THEN
  2088.             ActiveFilter := True
  2089.         ELSE
  2090.             ActiveFilter := False;
  2091.  
  2092.     END;
  2093.  
  2094.  
  2095. PROCEDURE CSFSaveWindow.Activate;
  2096.     Override;
  2097. { Set the gopher to the edit box }
  2098.  
  2099.     BEGIN
  2100.  
  2101.         INHERITED Activate;
  2102.         gGopher := fFileName;
  2103.  
  2104.     END;
  2105.  
  2106.  
  2107. PROCEDURE CSFSaveWindow.DoCommand (TheCommand: Longint);
  2108.     Override;
  2109. { Handle the commands for this subclass }
  2110.  
  2111.     BEGIN
  2112.  
  2113.         CASE TheCommand OF
  2114.             kSaveButton: 
  2115.                 DoSave;
  2116.             kSelection: 
  2117.                 DoSelection;
  2118.             kEmptyText: 
  2119.                 fSave.Deactivate;
  2120.             kNonEmptyText: 
  2121.                 fSave.Activate;
  2122.             OTHERWISE
  2123.                 INHERITED DoCommand(TheCommand);
  2124.         END;
  2125.  
  2126.     END;
  2127.  
  2128.  
  2129. PROCEDURE CSFSaveWindow.MoreUpdates;
  2130.     Override;
  2131. { Update edit box }
  2132.  
  2133.     VAR
  2134.         TheRect: Rect;
  2135.  
  2136.     BEGIN
  2137.  
  2138.         INHERITED MoreUpdates;
  2139.  
  2140.         IF IsVisible THEN
  2141.             BEGIN
  2142.                 TheRect := fFileName.Frame;
  2143.                 fFileName.FrameToEnclR(TheRect);
  2144.                 InSetRect(TheRect, -3, -3);
  2145.                 FrameRect(TheRect);
  2146.             END;
  2147.  
  2148.         Moveto(fViewRect.Left, fViewRect.Bottom + 21);
  2149.         DrawString(fPromptString);
  2150.  
  2151.     END;
  2152.  
  2153.  
  2154. PROCEDURE CSFSaveWindow.Free;
  2155.     Override;
  2156. { Dispose of the save button and edit box }
  2157.  
  2158.     BEGIN
  2159.  
  2160.         fSave.Free;
  2161.         fFileName.Free;
  2162.  
  2163.         INHERITED Free;
  2164.  
  2165.     END;
  2166.  
  2167.  
  2168. FUNCTION CSFSaveWindow.FileExists (vRefNum: Integer; TheName: Str255): Boolean;
  2169. { Find out if the file is already on the disk }
  2170.  
  2171.     VAR
  2172.         FndrInfo: FInfo;
  2173.         Err: OSErr;
  2174.         Ignore: Integer;
  2175.         ParamBlock: CInfoPBRec;
  2176.  
  2177.     BEGIN
  2178.  
  2179.         Prepare;
  2180.         WITH ParamBlock DO
  2181.             BEGIN
  2182.                 ioCompletion := NIL;
  2183.                 ioNamePtr := @TheName;
  2184.                 ioVRefNum := VRefNum;
  2185.                 ioDrDirID := 0;
  2186.                 ioDirID := 0;
  2187.                 ioFVersNum := 0;
  2188.                 ioFDirIndex := 0;
  2189.             END;
  2190.         Err := PBGetCatInfo(@ParamBlock, False);
  2191.         IF IsDirectory(@ParamBlock) THEN
  2192.             BEGIN
  2193.                 Err := NoErr;
  2194.             END;
  2195.  
  2196.         CASE Err OF
  2197.             fnfErr: 
  2198.                 BEGIN
  2199.                     FileExists := False;
  2200.                 END;
  2201.             NoErr: 
  2202.                 BEGIN
  2203.                     CASE Rename(TheName, vRefNum, TheName) OF
  2204.                         fLckdErr, vLckdErr, wPrErr: 
  2205.                             BEGIN
  2206.                                 Ignore := RedAlert(kLockedDisk);
  2207.                                 FileExists := True;
  2208.                                 Exit(FileExists);
  2209.                             END;
  2210.                     END;
  2211.                     ParamText(TheName, '', '', '');
  2212.                     IF RedAlert(kExistingFile) = 1 THEN
  2213.                         FileExists := True
  2214.                     ELSE
  2215.                         FileExists := False;
  2216.                 END;
  2217.             OTHERWISE
  2218.                 BEGIN
  2219.                     Ignore := RedAlert(kSystemError);
  2220.                     FileExists := True;
  2221.                 END;
  2222.         END;
  2223.  
  2224.     END;
  2225.  
  2226.  
  2227. PROCEDURE CSFSaveWindow.DoSave;
  2228. { Respond to the save button }
  2229.  
  2230.     VAR
  2231.         Temp: Integer;
  2232.         Err: OSErr;
  2233.  
  2234.     BEGIN
  2235.  
  2236.         IF fSave.IsActive THEN
  2237.             BEGIN
  2238.                 fGood := True;
  2239.                 fName := fFileName.GetStr255;
  2240.                 Err := GetVol(@fVName, Temp);
  2241.                 IF NOT FileExists(Temp, fName) THEN
  2242.                     BEGIN
  2243.                         DoCommand(kSelection);
  2244.                         FillDialog(fCurrentWD);
  2245.                     END;
  2246.             END;
  2247.  
  2248.     END;
  2249.  
  2250.  
  2251.  
  2252. PROCEDURE CSFDialog.ICSFDialog;
  2253. { Initialize and install our window subclass }
  2254.  
  2255.     BEGIN
  2256.  
  2257.         IDirector(gApplication);
  2258.         New(CSFWindow(ItsWindow));
  2259.         CSFWindow(ItsWindow).ICSFWindow(Self);
  2260.  
  2261.         FKeyEnable(False);
  2262.  
  2263.     END;
  2264.  
  2265.  
  2266. PROCEDURE CSFGetDialog.ICSFDialog;
  2267.     Override;
  2268. { Initialize and install our window subclass }
  2269.  
  2270.     BEGIN
  2271.  
  2272.         IDirector(gApplication);
  2273.         New(CSFGetWindow(ItsWindow));
  2274.         CSFGetWindow(ItsWindow).ICSFWindow(Self);
  2275.  
  2276.         FKeyEnable(False);
  2277.  
  2278.     END;
  2279.  
  2280.  
  2281. PROCEDURE CSFSaveDialog.ICSFDialog;
  2282.     Override;
  2283. { Initialize and install our window subclass }
  2284.  
  2285.     BEGIN
  2286.  
  2287.         IDirector(gApplication);
  2288.         New(CSFSaveWindow(ItsWindow));
  2289.         CSFSaveWindow(ItsWindow).ICSFWindow(Self);
  2290.  
  2291.         itsGopher := CSFSaveWindow(ItsWindow).fFileName;
  2292.  
  2293.         FKeyEnable(False);
  2294.  
  2295.  
  2296.     END;
  2297.  
  2298.  
  2299. PROCEDURE CSFSwitchboard.DoDiskEvent (macEvent: EventRecord);
  2300.     Override;
  2301. { Intercept disk events }
  2302.  
  2303.     BEGIN
  2304.  
  2305.         INHERITED DoDiskEvent(macEvent);
  2306.         gGopher.DoCommand(cmdDiskEvent);
  2307.  
  2308.     END;
  2309.  
  2310.  
  2311. PROCEDURE CSFApplication.ICSFApplication (extraMasters: integer; aRainyDayFund, aCreditLimit: Size);
  2312. { Install the new switchboard }
  2313.  
  2314.     CONST
  2315.         JUMPBUFFER_A1 = 5;    { Index of A1 in JumpBuffer }
  2316.  
  2317.     BEGIN
  2318.  
  2319.         MenuDisable := LongPtr($B54);                { Low-memory global    }
  2320.  
  2321.         nullStr := '';
  2322.  
  2323.         { We haven't reached the event loop yet.                 }
  2324.         { Flag A1 (jump addr) so we don't try to jump there.     }
  2325.  
  2326.         eventLoopJump[JUMPBUFFER_A1] := 0;
  2327.  
  2328.         InitToolbox;
  2329.  
  2330.         InitMemory(extraMasters, aRainyDayFund, aCreditLimit);
  2331.  
  2332.         { Instance Variables }
  2333.  
  2334.         IBureaucrat(NIL);
  2335.  
  2336.         { Install CSF switchboard }
  2337.         new(CSFSwitchboard(itsSwitchboard));
  2338.         itsSwitchboard.ISwitchboard;
  2339.  
  2340.         new(itsDirectors);
  2341.         itsDirectors.ICluster;
  2342.         new(itsIdleChores);
  2343.         itsIdleChores.IList;
  2344.         new(itsUrgentChores);
  2345.         itsUrgentChores.ICluster;
  2346.         urgentsToDo := FALSE;
  2347.         running := TRUE;
  2348.  
  2349.         { Global Variables }
  2350.  
  2351.         gSignature := '????';
  2352.         gHasWNE := WNEIsImplemented;
  2353.         gSleepTime := 0;                        { We want an early first Idle }
  2354.         new(gError);
  2355.  
  2356.         { Cursors }
  2357.  
  2358.         gIBeamCursor := GetCursor(iBeamCursor);
  2359.         HNoPurge(Handle(gIBeamCursor));
  2360.         gWatchCursor := GetCursor(watchCursor);
  2361.         HNoPurge(Handle(gWatchCursor));
  2362.  
  2363.         gUtilRgn := NewRgn;
  2364.  
  2365.         MakeDesktop;
  2366.         MakeClipboard;
  2367.         MakeDecorator;
  2368.         SetUpFileParameters;
  2369.         SetUpMenus;
  2370.  
  2371.         gGopher := SELF;
  2372.         gLastViewHit := NIL;
  2373.         gLastMouseUp.when := 0;
  2374.         gClicks := 0;
  2375.  
  2376.     END;
  2377.  
  2378. END.